package com.hyt.it.ogt.kq.service.admission.impl;

import static com.hyt.it.ogt.kq.common.gov.constant.ResponseCode.ADMISSION_TICKET_TEMPLATE_NOT_EXIST_FAIL;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hyt.core.base.BaseEntity;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.StringUtils;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.cj.model.entity.ProjectCollectInfo;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.gov.enums.CollectInfoEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.NotRoomCustomTemplateConfigEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.TemplateTypeEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.TicketDataSourceEnum;
import com.hyt.it.ogt.kq.common.gov.enums.admission.VirtualCustomTemplateConfigEnum;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketInfoService;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketTemplateService;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketTemplateVariableService;
import com.hyt.it.ogt.kq.service.gov.mapper.admission.AdmissionTicketTemplateMapper;
import com.hyt.it.ogt.kq.service.gov.model.dto.admission.AddOrUpdateAdmissionTemplateDTO;
import com.hyt.it.ogt.kq.service.gov.model.dto.admission.AdmissionTicketTemplateVariableVO;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.vo.admission.AdmissionStandardTemplateVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.admission.AdmissionTemplateVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.admission.TemplateConfigVO;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketInfo;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketTemplate;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketTemplateVariable;
import com.hyt.loginfo.model.Organization;
import com.hyt.loginfo.model.User;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import lombok.extern.slf4j.Slf4j;


/**
 * <p>
 * 准考证模板表 服务实现类
 * </p>
 *
 * @author yanghuankun@talkweb.com.cn
 * @since 2023-01-10
 */
@Service
@Slf4j
public class AdmissionTicketTemplateServiceImpl extends BaseServiceImpl<AdmissionTicketTemplateMapper, AdmissionTicketTemplate> implements IAdmissionTicketTemplateService {
    @Resource
    private IAdmissionTicketInfoService iAdmissionTicketInfoService;
    @Resource
    private IAdmissionTicketTemplateVariableService iAdmissionTicketTemplateVariableService;
    @Resource
    private IProjectCollectInfoService iProjectCollectInfoService;
    @Resource
    private ITaskService iTaskService;

    @Override
    public List<AdmissionStandardTemplateVO> standardList() {
        return this.lambdaQuery()
                .eq(BaseEntity::getDelFlag, Boolean.FALSE)
                .isNull(AdmissionTicketTemplate::getAdmissionTicketId)
                .list()
                .stream()
                .map(this::assembleAdmissionStandardTemplateVO)
                .collect(Collectors.toList());
    }

    /**
     * 装配准考证标准模板VO类
     *
     * @param admissionTicketTemplate
     * @return
     */
    private AdmissionStandardTemplateVO assembleAdmissionStandardTemplateVO(AdmissionTicketTemplate admissionTicketTemplate) {
        AdmissionStandardTemplateVO admissionStandardTemplateVO = BeanUtil.toBean(admissionTicketTemplate, AdmissionStandardTemplateVO.class);
        return admissionStandardTemplateVO;
    }

    /**
     * 获取准考证任务可以使用的模板
     *
     * @param officeId
     * @param deptId
     * @param admissionTicketInfoId
     * @return
     */
    @Override
    public List<AdmissionTemplateVO> admissionTicketTemplate(String officeId, String deptId, String admissionTicketInfoId) {
        List<AdmissionTemplateVO> admissionTemplateVOS = new LinkedList<>();
        Integer admissionTicketTemplateType = null;
        if (StrUtil.isNotBlank(admissionTicketInfoId)) {
            admissionTicketTemplateType = iAdmissionTicketInfoService.getById(admissionTicketInfoId).getAdmissionTicketTemplateType();
        }
        for (TemplateTypeEnum value : TemplateTypeEnum.values()) {
            AdmissionTemplateVO admissionTemplateVO = new AdmissionTemplateVO();
            admissionTemplateVO.setName(value.getText());
            admissionTemplateVO.setIsCurrentUse(Objects.equals(admissionTicketTemplateType, value.getCode()));
            admissionTemplateVO.setType(value.getCode());
            admissionTemplateVOS.add(admissionTemplateVO);
        }
        return admissionTemplateVOS;
    }

    /**
     * 获取标准模板
     *
     * @return
     */
    private List<AdmissionTicketTemplate> findStandardTemplate() {
        return lambdaQuery()
                .eq(BaseEntity::getDelFlag, Boolean.FALSE)
                .isNull(AdmissionTicketTemplate::getAdmissionTicketId)
                .list();
    }


    /**
     * 创建自定义模板
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AdmissionTicketTemplate createCustomTemplate(User currentUser, String deptId) {
        LocalDateTime now = LocalDateTime.now();
        AdmissionTicketTemplate admissionTicketTemplate = new AdmissionTicketTemplate();
        admissionTicketTemplate.setId(UUIDUtils.newSortUUID());
        admissionTicketTemplate.setCreateBy(currentUser.getId());
        admissionTicketTemplate.setCreateDate(now);
        admissionTicketTemplate.setUpdateBy(currentUser.getId());
        admissionTicketTemplate.setUpdateDate(now);

        admissionTicketTemplate.setOfficeId(currentUser.getOfficeid());
        admissionTicketTemplate.setDeptId(deptId);
        admissionTicketTemplate.setTemplateName(TemplateTypeEnum.CUSTOM.getText());

        save(admissionTicketTemplate);
        log.info("[准考证][新增模板]新增准考证模板：{} {}", currentUser, admissionTicketTemplate);
        return admissionTicketTemplate;
    }

    /**
     * 更新准考证模板的准考证任务id
     *
     * @param admissionTicketInfoId
     * @param templateId
     * @param currentUser
     */
    @Override
    public void updateAdmissionTicketInfoId(String admissionTicketInfoId, String templateId, User currentUser) {
        lambdaUpdate()
                .eq(BaseEntity::getDelFlag, false)
                .eq(BaseEntity::getId, templateId)
                .set(AdmissionTicketTemplate::getAdmissionTicketId, admissionTicketInfoId)
                .set(AdmissionTicketTemplate::getUpdateBy, currentUser.getId())
                .set(AdmissionTicketTemplate::getUpdateDate, LocalDateTime.now())
                .update();
        log.info("[准考证]更新准考证模板的准考证任务id：{} {} {}", currentUser, admissionTicketInfoId, templateId);
    }

    /**
     * 通过模板id判断是否标准模板
     *
     * @param templateId
     * @return
     */
    @Override
    public boolean isStandardTemplate(String templateId) {
        return lambdaQuery()
                .eq(BaseEntity::getDelFlag, false)
                .eq(BaseEntity::getId, templateId)
                .isNull(AdmissionTicketTemplate::getAdmissionTicketId)
                .count() > 0;
    }

    /**
     * 删除模板
     *
     * @param admissionInfoId
     * @param currentUser
     * @param deptId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteTemplateByAdmissionInfoId(String admissionInfoId, User currentUser, String deptId) {
        lambdaUpdate()
                .eq(AdmissionTicketTemplate::getAdmissionTicketId, admissionInfoId)
                .set(BaseEntity::getDelFlag, true)
                .set(BaseEntity::getUpdateBy, currentUser.getId())
                .set(BaseEntity::getUpdateDate, LocalDateTime.now())
                .update();

        iAdmissionTicketTemplateVariableService.lambdaUpdate()
                .eq(AdmissionTicketTemplateVariable::getAdmissionTicketId, admissionInfoId)
                .set(BaseEntity::getDelFlag, true)
                .set(BaseEntity::getUpdateBy, currentUser.getId())
                .set(BaseEntity::getUpdateDate, LocalDateTime.now())
                .update();
    }

    /**
     * 通过准考证id查询准考证模板
     *
     * @param admissionInfoId
     * @return
     */
    @Override
    public AdmissionTicketTemplate getByAdmissionInfoId(String admissionInfoId) {
        return lambdaQuery()
                .eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplate::getAdmissionTicketId, admissionInfoId)
                .last("limit 1").one();
    }

    /**
     * 新增或者更新准考证模板
     *
     * @param user
     * @param deptInfo
     * @param addOrUpdateAdmissionTemplateDTO
     * @return
     */
    @Override
    public void update(User user, Organization deptInfo, AddOrUpdateAdmissionTemplateDTO addOrUpdateAdmissionTemplateDTO) {
        lambdaUpdate()
                .eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplate::getAdmissionTicketId, addOrUpdateAdmissionTemplateDTO.getAdmissionTicketId())
                .eq(AdmissionTicketTemplate::getOfficeId, user.getOfficeid())
                .eq(AdmissionTicketTemplate::getDeptId, deptInfo.getId())
                .set(BaseEntity::getUpdateBy, user.getId())
                .set(BaseEntity::getUpdateDate, LocalDateTime.now())
                .set(AdmissionTicketTemplate::getTemplateHtml, addOrUpdateAdmissionTemplateDTO.getTemplateHtml())
                .set(AdmissionTicketTemplate::getTemplateParam, addOrUpdateAdmissionTemplateDTO.getTemplateParam())
                .update();
        iAdmissionTicketTemplateVariableService.update(addOrUpdateAdmissionTemplateDTO.getAdmissionTicketTemplateVariableDTOS(), addOrUpdateAdmissionTemplateDTO.getAdmissionTicketId(), user, deptInfo);
    }

    /**
     * 获取模板详情
     *
     * @param admissionId
     * @return
     */
    @Override
    public AdmissionTemplateVO byAdmissionId(String admissionId) {
        AdmissionTicketInfo admissionTicketInfo = iAdmissionTicketInfoService.getById(admissionId);
        AdmissionTicketTemplate admissionTicketTemplate = getOrThrow(admissionId);
        AdmissionTemplateVO admissionTicketTemplateVO = convertAdmissionTicketTemplateVO(admissionTicketTemplate);
        admissionTicketTemplateVO.setAdmissionInfoName(admissionTicketInfo.getAdmissionTicketName());
        List<AdmissionTicketTemplateVariable> admissionTicketTemplateVariables = listVariables(admissionTicketTemplate.getId());
        List<AdmissionTicketTemplateVariableVO> admissionTicketTemplateVariableVOS = convertAdmissionTicketTemplateVariableVOS(admissionTicketTemplateVariables);
        admissionTicketTemplateVO.setAdmissionTicketTemplateVariableVOList(admissionTicketTemplateVariableVOS);
        return admissionTicketTemplateVO;
    }

    /**
     * 转换模板变量vos
     *
     * @param admissionTicketTemplateVariables
     * @return
     */
    private List<AdmissionTicketTemplateVariableVO> convertAdmissionTicketTemplateVariableVOS(List<AdmissionTicketTemplateVariable> admissionTicketTemplateVariables) {
        List<AdmissionTicketTemplateVariableVO> admissionTicketTemplateVariableVOS = new ArrayList<>(admissionTicketTemplateVariables.size());
        for (AdmissionTicketTemplateVariable admissionTicketTemplateVariable : admissionTicketTemplateVariables) {
            admissionTicketTemplateVariableVOS.add(convertAdmissionTicketTemplateVariableVO(admissionTicketTemplateVariable));
        }
        return admissionTicketTemplateVariableVOS;
    }

    /**
     * 转换模板变量vo
     *
     * @param admissionTicketTemplateVariable
     * @return
     */
    private AdmissionTicketTemplateVariableVO convertAdmissionTicketTemplateVariableVO(AdmissionTicketTemplateVariable admissionTicketTemplateVariable) {
        AdmissionTicketTemplateVariableVO admissionTicketTemplateVariableVO = new AdmissionTicketTemplateVariableVO();
        admissionTicketTemplateVariableVO.setTemplateId(admissionTicketTemplateVariable.getTemplateId());
        admissionTicketTemplateVariableVO.setVariableCode(admissionTicketTemplateVariable.getVariableCode());
        admissionTicketTemplateVariableVO.setVariableName(admissionTicketTemplateVariable.getVariableName());
        admissionTicketTemplateVariableVO.setVariableDefaultValue(admissionTicketTemplateVariable.getVariableDefaultValue());
        admissionTicketTemplateVariableVO.setVariableSort(admissionTicketTemplateVariable.getVariableSort());
        admissionTicketTemplateVariableVO.setVariableDescription(admissionTicketTemplateVariable.getVariableDescription());
        admissionTicketTemplateVariableVO.setIsAllowUseDefault(admissionTicketTemplateVariable.getIsAllowUseDefault());
        return admissionTicketTemplateVariableVO;
    }

    /**
     * 转换VO
     *
     * @param admissionTicketTemplate
     * @return
     */
    private AdmissionTemplateVO convertAdmissionTicketTemplateVO(AdmissionTicketTemplate admissionTicketTemplate) {
        AdmissionTemplateVO admissionTemplateVO = new AdmissionTemplateVO();
        admissionTemplateVO.setId(admissionTicketTemplate.getId());
        admissionTemplateVO.setName(admissionTicketTemplate.getTemplateName());
        admissionTemplateVO.setType(TemplateTypeEnum.CUSTOM.getCode());
        admissionTemplateVO.setTemplateHtml(admissionTicketTemplate.getTemplateHtml());
        admissionTemplateVO.setTemplatePoster(admissionTicketTemplate.getTemplatePoster());
        admissionTemplateVO.setTemplateParam(admissionTicketTemplate.getTemplateParam());
        return admissionTemplateVO;
    }

    /**
     * 获取模板变量
     *
     * @param templateId
     * @return
     */
    private List<AdmissionTicketTemplateVariable> listVariables(String templateId) {
        return iAdmissionTicketTemplateVariableService.lambdaQuery()
                .eq(BaseEntity::getDelFlag, false)
                .eq(AdmissionTicketTemplateVariable::getTemplateId, templateId)
                .list();
    }

    /**
     * 获取准考证模板，不存在则报错
     *
     * @param admissionId
     * @return
     */
    private AdmissionTicketTemplate getOrThrow(String admissionId) {
        AdmissionTicketTemplate admissionTicketTemplate = getByAdmissionInfoId(admissionId);
        if (Objects.isNull(admissionTicketTemplate)) {
            throw new KqException(ADMISSION_TICKET_TEMPLATE_NOT_EXIST_FAIL);
        }
        return admissionTicketTemplate;
    }

    /**
     * 获取模板的可选配置
     *
     * @param admissionId
     * @return
     */
    @Override
    public List<TemplateConfigVO> listTemplateConfig(String admissionId) {

        LinkedList<TemplateConfigVO> templateConfigVOS = new LinkedList<>();
        Set<String> added = new HashSet<>();

        // 查询配置项
        AdmissionTicketInfo admissionTicketInfo = iAdmissionTicketInfoService.getById(admissionId);

        // 无考场和虚拟考场各自独有的配置
        if (Objects.equals(admissionTicketInfo.getAdmissionTicketDataSource(), TicketDataSourceEnum.NOT_ROOM.getCode())) {
            // 无考场配置
            for (NotRoomCustomTemplateConfigEnum value : NotRoomCustomTemplateConfigEnum.values()) {
                if (value == NotRoomCustomTemplateConfigEnum.NONE) {
                    continue;
                }
                
                if (!added.contains(value.getCode())) {
                    TemplateConfigVO templateConfigVO = new TemplateConfigVO();
                    templateConfigVO.setCode(value.getCode());
                    templateConfigVO.setTitle(value.getText());
                    templateConfigVO.setSort(value.getSort());
                    templateConfigVO.setDescription(value.getText());
                    templateConfigVOS.addFirst(templateConfigVO);
                    added.add(value.getCode());
                }
            }
        } else {
            // 虚拟考场配置
            for (VirtualCustomTemplateConfigEnum value : VirtualCustomTemplateConfigEnum.values()) {
                if (value == VirtualCustomTemplateConfigEnum.NONE) {
                    continue;
                }
                
                if (!added.contains(value.getCode())) {
                    TemplateConfigVO templateConfigVO = new TemplateConfigVO();
                    templateConfigVO.setCode(value.getCode());
                    templateConfigVO.setTitle(value.getText());
                    templateConfigVO.setSort(value.getSort());
                    templateConfigVO.setDescription(value.getText());
                    templateConfigVOS.addFirst(templateConfigVO);
                    added.add(value.getCode());
                }
            }
        }
        
        // 这里考务的采集信息和报名公用一套，需要换算成报名id
        String projectId = admissionTicketInfo.getExamId();
        Task task = iTaskService.getById(admissionTicketInfo.getExamId());
        if (null != task && StringUtils.isNotEmpty(task.getTaskBmId())) {
            projectId = task.getTaskBmId();
        }

        List<ProjectCollectInfo> projectCollectInfosByPid = iProjectCollectInfoService.getProjectCollectInfosByPid(projectId);
        List<ProjectCollectInfo> publicCollectConfigs = projectCollectInfosByPid.stream().filter(e -> CollectInfoEnum.isCollectInfo(e.getComponentName())).collect(Collectors.toList());
        List<ProjectCollectInfo> customCollectConfigs = projectCollectInfosByPid.stream().filter(e -> !CollectInfoEnum.isCollectInfo(e.getComponentName())).collect(Collectors.toList());

        // 基础配置项
        for (ProjectCollectInfo publicCollectConfig : publicCollectConfigs) {
            CollectInfoEnum value = CollectInfoEnum.getByCode(publicCollectConfig.getComponentName());
            if (!added.contains(value.getCode())) {
                TemplateConfigVO templateConfigVO = new TemplateConfigVO();
                templateConfigVO.setTitle(value.getText());
                templateConfigVO.setCode(value.getCode());
                templateConfigVO.setSort(CollectInfoEnum.addSort + publicCollectConfig.getOrderNum());
                templateConfigVO.setDescription(value.getText());
                templateConfigVOS.add(templateConfigVO);
                added.add(value.getCode());
            }
        }

        // 自定义配置项
        for (ProjectCollectInfo customCollectConfig : customCollectConfigs) {
            TemplateConfigVO templateConfigVO = new TemplateConfigVO();
            templateConfigVO.setTitle(customCollectConfig.getTitle());
            String code = CollectInfoEnum.convertCode(customCollectConfig.getComponentName(), customCollectConfig.getTitle());
            templateConfigVO.setCode(code);
            if (!added.contains(code)) {
                templateConfigVO.setSort(CollectInfoEnum.addSort + customCollectConfig.getOrderNum());
                templateConfigVO.setDescription(customCollectConfig.getDescription());
                templateConfigVOS.add(templateConfigVO);
                added.add(code);
            }
        }

        return templateConfigVOS.stream().sorted(Comparator.comparingInt(TemplateConfigVO::getSort)).collect(Collectors.toList());
    }

    /**
     * 准考证是否已经保存了自定义模板
     *
     * @param admissionTicketInfoId
     * @return
     */
    @Override
    public Boolean isSaveCustomTemplate(String admissionTicketInfoId) {
        AdmissionTicketTemplate admissionTicketTemplate = lambdaQuery()
                .eq(AdmissionTicketTemplate::getAdmissionTicketId, admissionTicketInfoId)
                .eq(AdmissionTicketTemplate::getDelFlag, false)
                .last("limit 1").one();
        return Objects.nonNull(admissionTicketTemplate) && StrUtil.isNotBlank(admissionTicketTemplate.getTemplateHtml());
    }

    /**
     * 准考证是否已经保存了模板
     *
     * @param admissionTicketInfo
     * @return
     */
    @Override
    public Boolean isSaveTemplate(AdmissionTicketInfo admissionTicketInfo) {
        Integer admissionTicketTemplateType = admissionTicketInfo.getAdmissionTicketTemplateType();
        if (TemplateTypeEnum.CUSTOM.getCode().equals(admissionTicketTemplateType)) {
            return isSaveCustomTemplate(admissionTicketInfo.getId());
        } else {
            // 标准模板已经保存了对应的html
            return true;
        }
    }
}
